// Copyright (c) 2010 god6or@gmail.com under MIT license.

package ul.graph.chart

import java.awt.{Dimension,Color,Font,Point,Polygon,Stroke,Graphics2D,Canvas}
import swing.{Panel}
import collection.mutable.{ArrayBuffer}


object Chart {
    object types extends Enumeration {
        val PlotLinear = Value
    }
    object marks extends Enumeration {
        val MarksNone = Value
    }
    object drawType extends Enumeration {
        val DrawNone,DrawPoints,DrawLines,DrawSmoothLines,DrawBars = Value
    }
    object grids extends Enumeration {
        val GridNone,GridPoints,GridLines = Value
    }
}

class ChartGrid(
) {
    var chart: Chart = null

    var __color: Int = 0x00FFFFFF
    def color = __color
    def color_= (newColor: Int) = { __color = newColor }

    var __bgColor: Int = 0x00000000
    def bgColor = __bgColor
    def bgColor_= (newBGColor: Int) = { __bgColor = newBGColor }
}

class ChartAxis(
) {
    var chart: Chart = null

    var __title: String = ""
    def title = __title
    def title_= (newTitle: String) = { __title = newTitle }
    
    var __markingFmt = "%6.2f"
    def markingFmt = __markingFmt
    def markingFmt_= (newMarkingFmt: String) = { __markingFmt = newMarkingFmt }

    var __markingConv: (Double)=>String = (x: Double) => format(markingFmt,x)
    def markingConv = __markingConv
    def markingConv_= (newMarkingConv: (Double)=>String) = { __markingConv = newMarkingConv }
    
    var __autoRange = false
    def autoRange = __autoRange
    def autoRange_= (newAutoRange: Boolean) = { __autoRange = newAutoRange }
    
    var __bounds = (Double.NaN, Double.NaN)
    def bounds = __bounds
    def bounds_= (newBounds: (Double, Double)) = { __bounds = newBounds }
    
    var __color = 0x00FFFFFF
    def color = __color
    def color_= (newColor: Int) = { __color = newColor }
    
    def calcBounds = {
    }
}

class ChartPlot(
    var data: ArrayBuffer[ ArrayBuffer[ Double ]]
) {
    var chart: Chart = null // parent chart

    var __title: String = ""
    def title = __title
    def title_= (newTitle: String) = { __title = newTitle }

    var __color = 0x00FFFFFF
    def color = __color
    def color_= (newColor: Int) = { __color = newColor }

    var __drawType = Chart.drawType.DrawSmoothLines
    def drawType = __drawType
    def drawType_= (newDrawType: Chart.drawType.Value) = { __drawType = newDrawType }

    var __marks = Chart.marks.MarksNone
    def marks = __marks
    def marks_= (newMarks: Chart.marks.Value) = { __marks = newMarks }

    var min = (for (axisData <- data) yield axisData.min).toArray
    var max = (for (axisData <- data) yield axisData.max).toArray
}

trait Chart {
    
    val thisChart = this

    var __chartType = Chart.types.PlotLinear
    def chartType = __chartType
    def chartType_= (newChartType: Chart.types.Value) = { __chartType = newChartType }
    
    var __chartAutoRange = false
    def chartAutoRange = __chartAutoRange
    def chartAutoRange_= (newChartAutoRange: Boolean) = { __chartAutoRange = newChartAutoRange }

    var __chartXRange = (Double.NaN, Double.NaN)
    def chartXRange = __chartXRange
    def chartXRange_= (newChartXRange: (Double, Double)) = { __chartXRange = newChartXRange }

    var __chartWidth = 0
    def chartWidth = __chartWidth
    def chartWidth_= (newChartWidth: Int) = { __chartWidth = newChartWidth }
    var __chartHeight = 0
    def chartHeight = __chartHeight
    def chartHeight_= (newChartHeight: Int) = { __chartHeight = newChartHeight }

    var chartGrid = Chart.grids.GridNone

    var chartAxes: Array[ChartAxis] = null
    def chartAxesNum = chartAxes.length
    def chartAxesNum_= ( newChartAxesNum: Int ) = {
        chartAxes = (for (i <- 1 to newChartAxesNum) yield new ChartAxis() { chart = thisChart }).toArray
    }

    val chartPlots = new ArrayBuffer[ChartPlot]
    def chartPlotsNum = chartPlots.length
    def chartPlotAdd( plot: ChartPlot ) = {
        plot.chart = this
        chartPlots += plot
    }
}

trait Chart2D extends Chart {
    chartAxesNum = 2
}

trait Chart3D extends Chart {
    chartAxesNum = 3
}

